package tr.edu.metu.is.mega.client.course.lecturenote;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.core.AsyncCallbackAdapter;
import tr.edu.metu.is.mega.client.core.DialogCallbackAdapter;
import tr.edu.metu.is.mega.client.core.DownloadHelper;
import tr.edu.metu.is.mega.client.core.MegaUtil;
import tr.edu.metu.is.mega.client.core.event.SelectionEventBus;
import tr.edu.metu.is.mega.client.core.event.SelectionEventListener;
import tr.edu.metu.is.mega.client.course.CourseChangeEvent;
import tr.edu.metu.is.mega.client.resource.MEGAIconBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.service.GwtLectureNoteService;
import tr.edu.metu.is.mega.client.service.GwtLectureNoteServiceAsync;
import tr.edu.metu.is.mega.common.dto.CourseDTO;
import tr.edu.metu.is.mega.common.dto.LectureNoteDTO;
import tr.edu.metu.is.mega.common.dto.UserRole;

import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * Window for defining and changing lecture note records.
 */
public class LectureNoteManagementPanel extends LayoutContainer {

    private MEGAResourceBundle resourceBundle;

    private MEGAIconBundle iconBundle;

    private Grid<BeanModel> grid;

    private BeanModelFactory beanModelFactory;

    private CourseDTO course;

    private final UserRole role;

    /**
     * Default constructor.
     */
    public LectureNoteManagementPanel(UserRole role) {
        this.role = role;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
        setLayout(new FitLayout());
        resourceBundle = MEGAResources.RESOURCEBUNDLE;
        iconBundle = MEGAResources.ICONBUNDLE;
        beanModelFactory = BeanModelLookup.get().getFactory(LectureNoteDTO.class);

        FieldSet set = new FieldSet();
        set.setHeight(400);
        if (role == UserRole.STUDENT) {
            set.setHeight(300);
        }
        set.setLayout(new FillLayout());
        set.setHeading(resourceBundle.lectureNotesManagementHeading());

        ContentPanel panel = new ContentPanel();
        panel.setHeaderVisible(false);

        panel.add(getGrid());
        panel.setTopComponent(getToolBar());

        set.add(panel);
        add(set);
        SelectionEventBus.getInstance().registerListener(CourseChangeEvent.Update.class, new SelectionEventListener<CourseDTO>() {

            @Override
            public void selectionChanged(CourseDTO selectedObject) {
                course = selectedObject;
                getService().getLectureNotes(selectedObject, new AsyncCallbackAdapter<List<LectureNoteDTO>>() {

                    @Override
                    public void onSuccess(List<LectureNoteDTO> result) {
                        setLectureNotes(result);
                    }
                });

            }
        });
    }

    /**
     * Initializes and returns toolbar.
     * 
     * @return toolbar
     */
    private ToolBar getToolBar() {
        ToolBar toolBar = new ToolBar();
        toolBar.setMinButtonWidth(70);
        toolBar.setSpacing(5);

        Button addButton = new Button(resourceBundle.add(), AbstractImagePrototype.create(iconBundle.add()));
        addButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (course != null) {
                    LectureNoteEditDialog dialog = new LectureNoteEditDialog(course);
                    dialog.create(new LectureNoteDTO(), new DialogCallbackAdapter<LectureNoteDTO>() {

                        @Override
                        public void onOk(LectureNoteDTO param) {
                            getService().createLectureNote(param, new AsyncCallbackAdapter<LectureNoteDTO>() {

                                @Override
                                public void onSuccess(LectureNoteDTO result) {
                                    SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.UPDATE, course);
                                }
                            });

                        }
                    });
                } else {
                    Info.display("", "Choose course first");
                }
            }
        });

        Button deleteButton = new Button(resourceBundle.delete(), AbstractImagePrototype.create(iconBundle.delete()));
        deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    LectureNoteDTO dto = grid.getSelectionModel().getSelectedItem().getBean();
                    getService().deleteLectureNote(dto, new AsyncCallbackAdapter<Void>() {

                        @Override
                        public void onSuccess(Void result) {
                            grid.getStore().remove(grid.getSelectionModel().getSelectedItem());
                        }
                    });
                }
            }
        });

        Button downloadButton = new Button(resourceBundle.download(), AbstractImagePrototype.create(iconBundle.download()));
        downloadButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    DownloadHelper.downloadFile(((LectureNoteDTO) grid.getSelectionModel().getSelectedItem().getBean()).getFullFilePath());
                }
            }
        });

        if (role != UserRole.STUDENT) {
            toolBar.add(addButton);
            toolBar.add(deleteButton);
        }
        toolBar.add(downloadButton);

        return toolBar;
    }

    /**
     * Returns activity grid.
     * 
     * @return grid
     */
    private Grid<BeanModel> getGrid() {
        if (grid == null) {

            ListStore<BeanModel> store = new ListStore<BeanModel>();

            List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
            columns.add(new ColumnConfig(LectureNoteDTO.FIELD_DESCRIPTION, resourceBundle.lectureNotesManagementDescription(), 150));
            columns.add(new ColumnConfig(LectureNoteDTO.FIELD_FILEPATH, resourceBundle.lectureNotesManagementFilePath(), 100));

            ColumnModel cm = new ColumnModel(columns);

            grid = new Grid<BeanModel>(store, cm);

            MegaUtil.decoradeGridViewWithAutoHeight(grid, true);

        }
        return grid;
    }

    /**
     * Adds lecture notes to grid
     * 
     * @param lecture note list
     */
    public void setLectureNotes(List<LectureNoteDTO> lectureNoteList) {
        grid.getStore().removeAll();
        for (LectureNoteDTO lectureNote : lectureNoteList) {
            grid.getStore().add(beanModelFactory.createModel(lectureNote));
        }
    }

    /**
     * Gets lecture notes from grid.
     * 
     * @return list of lecture notes
     */
    public List<LectureNoteDTO> getLectureNotes() {
        List<LectureNoteDTO> notes = new ArrayList<LectureNoteDTO>(grid.getStore().getModels().size());
        for (BeanModel model : grid.getStore().getModels()) {
            notes.add((LectureNoteDTO) model.getBean());
        }
        return notes;
    }

    public static GwtLectureNoteServiceAsync getService() {
        return GwtLectureNoteService.Util.getInstance();
    }

}
